package crypt;

import java.security.InvalidKeyException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;

/**
 * 
 * @author Julian Beisert
 * @version 1.0
 */
public class CryptRSA {

	private KeyPair _keyPair;
	private static CryptRSA _instance = null;

	private CryptRSA() {
	}

	/**
	 * generate Key Pair
	 */
	private void generateKeyPair() {
		KeyPairGenerator kpg = null;
		KeyPair kp = null;
		try {
			kpg = KeyPairGenerator.getInstance("RSA");
		} catch (NoSuchAlgorithmException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		kpg.initialize(2048);
		kp = kpg.genKeyPair();
		this._keyPair = kp;
	}

	/**
	 * 
	 * 
	 * 
	 * @return get Private Key from generated KeyPair
	 */
	private PrivateKey getPrivateKey() {
		PrivateKey priv = this._keyPair.getPrivate();
		return priv;

	}

	/**
	 * 
	 * 
	 * 
	 * @return get Public Key from generated KeyPair
	 */
	public PublicKey getPublicKey() {
		PublicKey pub = this._keyPair.getPublic();
		return pub;

	}

	/**
	 * 
	 * @param data
	 *            data to encrypt
	 * @param pubKey
	 *            public key from client
	 * @return encrypted data
	 */
	public byte[] encrypt(byte[] data, PublicKey pubKey) {
		Cipher cipher = null;
		try {
			cipher = Cipher.getInstance("RSA");
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (NoSuchPaddingException e) {
			e.printStackTrace();
		}
		try {
			cipher.init(Cipher.ENCRYPT_MODE, pubKey);
		} catch (InvalidKeyException e) {
			e.printStackTrace();
		}
		byte[] encrypt = null;
		try {
			encrypt = cipher.doFinal(data);
		} catch (IllegalBlockSizeException | BadPaddingException e) {
			e.printStackTrace();
		}
		return encrypt;
	}

	/**
	 * 
	 * @param data
	 *            data to decrypt
	 * @return decrypted data
	 */
	public byte[] decrypt(byte[] data) {
		Cipher cipher = null;
		try {
			cipher = Cipher.getInstance("RSA");
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (NoSuchPaddingException e) {
			e.printStackTrace();
		}
		try {
			cipher.init(Cipher.DECRYPT_MODE, getPrivateKey());
		} catch (InvalidKeyException e) {
			e.printStackTrace();
		}
		byte[] encrypt = null;
		try {
			encrypt = cipher.doFinal(data);
		} catch (IllegalBlockSizeException | BadPaddingException e) {
			e.printStackTrace();
		}
		return encrypt;
	}

	/**
	 * 
	 * @return Singelton CryptRSA Object
	 */
	public static CryptRSA getInstance() {
		if (_instance == null) {
			_instance = new CryptRSA();
			_instance.generateKeyPair();
			;
		}
		return _instance;

	}

}
